/*
 * @Author: yangni 920556271@qq.com
 * @Date: 2023-12-25 17:42:54
 * @LastEditors: yangni 920556271@qq.com
 * @LastEditTime: 2024-04-18 18:54:25
 * @FilePath: /yt-devops/lib/pages/site/site_overview/component/animate_line/animate_line_view.dart
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */

import 'dart:ui';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:svg_path_parser/svg_path_parser.dart';
import 'package:yt_devops/components/gaps.dart';
import 'package:yt_devops/pages/site/site_overview/site_overview_model.dart';

import 'line_painter.dart';
import 'point_painter.dart';

class AnimateLineModel {
  final String path;
  final Color lineColor;
  final FlowDirection direction;

  AnimateLineModel({
    required this.path,
    this.lineColor = const Color(0xFFCDCED0),
    this.direction = FlowDirection.stops,
  });
}

class AnimateLineView extends StatefulWidget {
  final List<AnimateLineModel> lineList;

  final Size? size;

  final Duration duration;

  const AnimateLineView(
      {super.key,
      required this.lineList,
      this.size,
      this.duration = const Duration(milliseconds: 2500)});

  @override
  State<AnimateLineView> createState() => _AnimateLineViewState();
}

class _AnimateLineViewState extends State<AnimateLineView>
    with TickerProviderStateMixin {
  late AnimationController _controller;

  Map<String, Animation> _animationMap = {};

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(vsync: this, duration: widget.duration);

    getAnimSequence(widget.lineList);

    _controller.repeat();
  }

  @override
  void didUpdateWidget(covariant AnimateLineView oldWidget) {
    if (oldWidget.lineList != widget.lineList) {
      getAnimSequence(widget.lineList);
    }

    super.didUpdateWidget(oldWidget);
  }

  @override
  void dispose() {
    _controller.dispose();

    super.dispose();
  }

  /// 生成所有路径的运动分镜
  getAnimSequence(List<AnimateLineModel> lineList) {
    for (var action in lineList) {
      final Animatable<double> positionTween = Tween<double>(
        begin: 0,
        end: 1,
      );
      final Animation<double> positionCurve;
      if (action.direction == FlowDirection.ins) {
        positionCurve = _controller.drive(
          CurveTween(curve: const Interval(0.5, 1, curve: Curves.linear)),
        );
        _animationMap[action.path] = positionTween.animate(positionCurve);
      } else if (action.direction == FlowDirection.outs) {
        positionCurve = _controller.drive(
          CurveTween(curve: const Interval(0.0, 0.5, curve: Curves.linear)),
        );

        _animationMap[action.path] = positionTween.animate(positionCurve);
      }
    }
  }

  bool isStop(FlowDirection flowDirection) =>
      flowDirection == FlowDirection.stops;

  Widget getAnimationWidget(AnimateLineModel model) {
    if (isStop(model.direction)) {
      return Gaps.empty;
    }

    var animate = _animationMap[model.path];
    var svgPath = parseSvgPath(model.path);
    var pathMetric = svgPath.computeMetrics().first;
    var pathLength = pathMetric.length;

    return AnimatedBuilder(
      animation: _controller,
      builder: (BuildContext context, Widget? child) {
        if (animate?.value == null ||
            animate?.value == 0 ||
            animate?.value >= 1) {
          return Gaps.empty;
        }

        /// ins 则反方向运动
        var animateOffset = model.direction == FlowDirection.ins
            ? 1 - animate!.value
            : animate!.value;

        final Tangent? tangent =
            pathMetric.getTangentForOffset(pathLength * animateOffset);

        return Transform(
          transform: Matrix4.identity()
            ..translate(tangent!.position.dx - 5.w, tangent.position.dy - 3.w),
          child: CustomPaint(
            size: Size(10.w, 6),
            painter: const PonitPainter(Color(0xFFFF974A)),
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    var boxSize = widget.size ?? Size(149.w, 149.w);
    return SizedBox(
      width: boxSize.width,
      height: boxSize.height,
      child: Stack(
        children: [
          ...widget.lineList
              .map(
                (e) => CustomPaint(
                  painter: LinPainter(
                    e.path,
                    e.lineColor,
                  ),
                  size: boxSize,
                ),
              )
              .toList(),
          ...widget.lineList.map((e) => getAnimationWidget(e)).toList(),
        ],
      ),
    );
  }
}
